﻿// XmlVisualizer
// Copyright (C) 2009  Roman Betík - rbetik@gmail.com

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

namespace XmlVisualizer.Exceptions
{
    using System;
    using System.Collections;
    using System.Collections.ObjectModel;
    using System.Configuration;
    using System.IO;
    using System.Reflection;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    using System.Xml;
    using System.Xml.Schema;
    using System.Xml.XPath;

    using VS;

    using XmlVisualizer.Controllers;
    using XmlVisualizer.DiagramDesigner;
    using XmlVisualizer.DiagramDesigner.Controls;
    using XmlVisualizer.Logging;
    using XmlVisualizer.Models;

    /// <summary>
    /// Static exception handling class.
    /// </summary>
    public static class ExceptionHandling
    {
        /// <summary>
        /// Shows error message.
        /// </summary>
        /// <param name="message">message to display.</param>
        public static void ShowMessage(string message)
        {
            MessageBox.Show(message, "Exception caught", MessageBoxButton.OK, MessageBoxImage.Error);
        }       

        /// <summary>
        /// Handles exception. Shows exception message and/or logs the exception.
        /// </summary>
        /// <param name="ex">Exception to handle.</param>
        public static void HandleException(Exception ex)
        {
            bool debugMode = bool.Parse(ConfigurationSettings.AppSettings["debugMode"]);
            string longMessage = Exceptions.ExceptionHandling.CreateLongMessage(ex);
            switch (debugMode)
            {
                case true:
                    Log.AddMessage(LoggerLevels.Error, "Exception", longMessage);
                    ShowException(longMessage);
                    break;
                case false:
                    Log.AddMessage(LoggerLevels.Error, "Exception", longMessage);
                    ShowException(Exceptions.ExceptionHandling.CreateShortMessage(ex));
                    break;
            }
        }

        /// <summary>
        /// Handles FileFormatException which occurs when user loads file and the file is corrupted.
        /// </summary>
        /// <param name="ex">FileFormatException instance</param>
        public static void HandleException(FileFormatException ex)
        {
            string longMessage = Exceptions.ExceptionHandling.CreateLongMessage(ex);
            Log.AddMessage(LoggerLevels.Error, "Exception", longMessage);
            ShowException("File is corrupted. See log file for more information.");
        }

        /// <summary>
        /// Handles XPathException which occurs when user mistypies XPath expression.
        /// </summary>
        /// <param name="ex">XPathException instance</param>
        public static void HandleException(XPathException ex)
        {
            string longMessage = Exceptions.ExceptionHandling.CreateLongMessage(ex);
            Log.AddMessage(LoggerLevels.Error, "Exception", longMessage);
            ShowException("XPath exception: " + ex.Message);
        }

        private static void ShowException(string message)
        {
            MessageBox.Show(message, "Exception caught", MessageBoxButton.OK, MessageBoxImage.Error);
        }

        private static string CreateShortMessage(Exception ex)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("Exception message: {0}\n", ex.Message);
            return sb.ToString();
        }

        private static string CreateLongMessage(Exception ex)
        {
            StringBuilder sb = new StringBuilder();
            MethodBase targetSite = ex.TargetSite;

            sb.AppendFormat("Exception type: {0}", ex.GetType());
            sb.AppendLine();
            sb.AppendFormat("Exception message: {0}", ex.Message);
            sb.AppendLine();
            sb.AppendFormat("Calling method's name: {0}", targetSite.Name);
            sb.AppendLine();
            sb.AppendFormat("Module name: {0}", targetSite.Module.Name);
            sb.AppendLine();
            sb.AppendLine("StackTrace:");
            sb.AppendLine(ex.StackTrace);

            if (ex is TargetInvocationException || ex.InnerException != null)
            {
                sb.AppendLine();
                sb.AppendLine("InnerException:");
                sb.AppendLine(ex.InnerException.Message);
                sb.AppendLine("InnerException StackTrace:");
                sb.AppendLine(ex.InnerException.StackTrace);
                sb.AppendLine();
            }

            return sb.ToString();
        }
    }
}